#include <47func.h>
typedef struct node_s{
    int data;
    struct node_s * pNext;
} node_t;
typedef struct queue_s{
    node_t * pFront;
    node_t * pRear;
    int size;
} queue_t;
typedef struct shareRes_s{
    queue_t queue;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}shareRes_t;
void Enqueue(queue_t *pQueue, int data){
    node_t * pNew = (node_t *)calloc(1,sizeof(node_t));
    pNew->data = data;
    if(pQueue->size == 0){
        pQueue->pFront = pNew;
        pQueue->pRear = pNew;
    }
    else{
        pQueue->pRear->pNext = pNew;
        pQueue->pRear = pNew;
    }
    ++pQueue->size;
}
int Dequeue(queue_t * pQueue){
    node_t * pCur = pQueue->pFront;
    pQueue->pFront = pCur->pNext;
    int result = pCur->data;
    free(pCur);
    --pQueue->size;
    return result;
}
void *producer(void *arg){
    shareRes_t * pShareRes = (shareRes_t *)arg;
    while(1){
        // produce
        pthread_mutex_lock(&pShareRes->mutex);
        while(pShareRes->queue.size >= 10){
            pthread_cond_wait(&pShareRes->cond,&pShareRes->mutex);
        }
        int data = rand()%100;
        Enqueue(&pShareRes->queue,data);
        printf("producer, data = %d, size = %d\n", data, pShareRes->queue.size);
        pthread_cond_broadcast(&pShareRes->cond);
        pthread_mutex_unlock(&pShareRes->mutex);
        sleep(3);
    }
}
void *consumer(void *arg){
    shareRes_t * pShareRes = (shareRes_t *)arg;
    sleep(5);
    while(1){
        // consume
        pthread_mutex_lock(&pShareRes->mutex);
        while(pShareRes->queue.size <= 0){
            pthread_cond_wait(&pShareRes->cond,&pShareRes->mutex);
        }
        printf("consumer, data = %d\n", Dequeue(&pShareRes->queue));
        printf("size = %d\n",pShareRes->queue.size);
        pthread_cond_broadcast(&pShareRes->cond);
        pthread_mutex_unlock(&pShareRes->mutex);
        sleep(1);
    }

}
int main(int argc, char *argv[])
{
    shareRes_t shareRes;
    pthread_mutex_init(&shareRes.mutex,NULL);
    pthread_cond_init(&shareRes.cond,NULL);
    memset(&shareRes.queue,0,sizeof(shareRes.queue));//pRear pFront NULL size
    for(int i = 0; i < 8; ++i){
        Enqueue(&shareRes.queue,rand()%100);
    }
    pthread_t tid1,tid2,tid3,tid4,tid5;
    pthread_create(&tid1,NULL,producer,&shareRes);
    pthread_create(&tid2,NULL,producer,&shareRes);
    pthread_create(&tid3,NULL,producer,&shareRes);
    pthread_create(&tid4,NULL,consumer,&shareRes);
    pthread_create(&tid5,NULL,consumer,&shareRes);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    pthread_join(tid3,NULL);
    pthread_join(tid4,NULL);
    pthread_join(tid5,NULL);
    return 0;
}

